package com.garen.orm.dao.impl;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Repository;

import com.garen.orm.ConvertColumn;
import com.garen.orm.OrmDBType;
import com.garen.orm.dao.IOrmDao;

@Repository("ormmetadao")
public class OrmMetaDaoImpl   implements IOrmDao {

	protected static Log log = LogFactory.getLog(OrmMetaDaoImpl.class);
	private OrmDBType ormdb;
	
	@Override
	public List<String> getTables() {
		List<String> tablelist = new ArrayList<String>();
		Connection conn = null;
		if(ormdb == null) return new ArrayList<>();
		DataSource ds = ormdb.getDataSource();
		try {
			conn = ds.getConnection();
			DatabaseMetaData databaseMetaData = conn.getMetaData();
			ResultSet tableSet = null;
			if(ormdb.isOracle()){
				String schem = ormdb.getSchem();			
				tableSet = databaseMetaData.getTables(null, schem, "%", 
						new String[]{"TABLE"});
			}else{
				tableSet = databaseMetaData.getTables(null, "%", "%",
						new String[]{"TABLE"});
			}
			while(tableSet.next()){
				String tableName = tableSet.getString("TABLE_NAME");
				if(ormdb.isOracle()){
					if(tableName.indexOf("==$0") != -1) continue;
				}
				tablelist.add(tableName);
			}
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(null != conn){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return tablelist;
	}

	//测试方法
	protected void test(ResultSet columnSet) throws SQLException{
		ResultSetMetaData meta = columnSet.getMetaData();
		for(int size = meta.getColumnCount();size > 0;size--){
			log.debug(meta.getColumnName(size));
		}
	}
	
	@Override
	public Set<ConvertColumn> getColumnInfo(String tableName) {
		Set<ConvertColumn> colset = new HashSet<ConvertColumn>();
		DatabaseMetaData databaseMetaData;
		Connection conn = null;
		if(ormdb == null) return new HashSet<>();
		DataSource ds = ormdb.getDataSource();
		try {
			 conn = ds.getConnection();
			databaseMetaData = conn.getMetaData();
			ResultSet columnSet = null;
			if(ormdb.isOracle()){
				columnSet = databaseMetaData.getColumns(null, ormdb.getSchem(), 
						tableName, "%");
			}else{
				columnSet = databaseMetaData.getColumns(null, "%", tableName, "%");
			}
			//获取所有列
			while(columnSet.next()){
				//log.debug(columnSet.getString("TABLE_CAT") +","+ columnSet.getString("TABLE_SCHEM"));
				ConvertColumn col = new ConvertColumn();
				String colName = columnSet.getString("COLUMN_NAME");
				col.setColName(colName);
				col.setComment(columnSet.getString("REMARKS"));
				String typeName = columnSet.getString("TYPE_NAME").toLowerCase();
				col.setColType(typeName);
				//log.debug(colName + "=" +columnSet.getInt("DATA_TYPE") +"="+ typeName);
				//是否为空
				col.setNullable("YES".equals(columnSet.getString("IS_NULLABLE")));
				if(ormdb.isOracle()){
					col.setAutoIncrement(false);
				}else if(ormdb.isMssql()){//判断是否主键
					if(typeName.endsWith(" identity"))
						col.setAutoIncrement(true);//自增
				}else{
					col.setAutoIncrement("YES".equals(columnSet.getString("IS_AUTOINCREMENT")));
				}
				col.convert();//表列--》 字段的转换
				colset.add(col);
			}
			ResultSet pkCols = null;
			if(ormdb.isOracle()){
				pkCols = databaseMetaData.getPrimaryKeys(null, ormdb.getSchem(),
						tableName);
			}else if(ormdb.isMssql()){
				pkCols = databaseMetaData.getPrimaryKeys(null, "dbo", tableName);
			}else{
				pkCols = databaseMetaData.getPrimaryKeys(null, "%", tableName);
			}
			if(pkCols == null) return colset;
			while(pkCols.next()){
				//test(pkCols);
				String colName = pkCols.getString("COLUMN_NAME");
				log.debug(colName + "主键");
				for(ConvertColumn col : colset){
					if(colName.equals(col.getColName())){
						col.setID(true);//设置为主键
					}
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			if(null != conn){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return colset;
	}

	public void setOrmdb(OrmDBType ormdb) {
		this.ormdb = ormdb;
	}

}
